/*
 *  $Id: Application.cs 1246 2011-03-23 14:19:35Z thenn.erannor $
 *  This file is a part of Ragima CCG.
 *  (C) 2008-2010 Ragima development group.
 *
 *  Licensed under the terms of the GNU GPL License version 2.
 *
 */

using System;
using System.IO;
using System.Reflection;
using System.Windows.Forms;

using AgateLib;
using AgateLib.DisplayLib;
using AgateLib.InputLib;

using Ragima.Languages;

namespace Ragima {
    public static class Application {
        [STAThread]
        static void Main(string[] args) {
            Start(RagimaApplication, args);
        }

        public static void Start(SimpleEvent mainAction, string[] args) {
            AllLanguages.AddLanguages(Paths.Languages, true);
            if (AllLanguages.Count == 0) {
                MessageBox.Show("This version has no language files. Sorry, the program can't run without them.", "Ragima", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            Nereal.Serialization.SerializationConfig.InfoManager.RegisterInfo(Assembly.Load("Ragima.Serialization"));
            Ragima.Serialization.Resolvers.Register(Nereal.Serialization.Serializer.Default);
            _config = Config.Load();

            Console.WriteLine(GetFullName());
            foreach (Language lang in AllLanguages.GetLanguages())
                Console.WriteLine(Resources.Application.LoadedLanguage.GetText(lang.LangCode, lang.ResourceCount));
            using (AgateSetup setup = new AgateSetup(GetFullName(), args)) {
                setup.AskUser = false;
                try {
                    setup.InitializeDisplay();
                } catch (Exception e) {
                    ErrorReport(e, true);
                    return;
                }
                try {
                    setup.InitializeAudio();
                } catch (AgateException e) {
                    ErrorReport(e, false);
                    MessageBox.Show(Resources.Application.ErrorAudio.GetText(), Resources.Application.Error.GetText(), MessageBoxButtons.OK, MessageBoxIcon.Error);
                    setup.UseAudio = false;
                } catch (Exception e) {
                    ErrorReport(e, true);
                    return;
                }
                if (setup.WasCanceled)
                    return;

                Core.AutoStackTrace = true;

                _config.Sound.DriverEnabled = setup.UseAudio;

             
                try {
                    Initialize();
                    
                    CardManager.Export("stats.html", new HtmlStatisticCardExporter());
                    CardManager.Export("cards.xml", new XmlCardExporter());
                } catch (Exception e) {
                    ErrorReport(e, true);
                    return;
                }

                if (mainAction != null)
                    mainAction();
            }
            _config.Save();
        }

        private static void RagimaApplication() {
            //NewGame();
            CurrentScene = MainMenu.Instance;
            Run();
        }

        public static string GetCurrentVersion() {
            // TODO: нормальное получение версии
            Assembly asm = Assembly.GetExecutingAssembly();
            Version version = asm.GetName().Version;
            return version.ToString(2);
        }
        public static string GetFullName() {
            return Resources.Application.GameName.GetText(GetCurrentVersion());
        }

        private static Config _config;
        private static DisplayWindow _window;
        private static OldScene _scene;
        private static bool _terminated;

        public static LanguageList AllLanguages {
            get { return Language.AllLanguages; }
        }

        public static Config Config {
            get { return _config; }
        }

        public static OldScene CurrentScene {
            get { return _scene; }
            set {
                if (_scene == value)
                    return;
                if (_scene != null)
                    _scene.FinalizeScene();
                _scene = value;
                if (_scene != null)
                    _scene.InitializeScene();
            }
        }

        public static bool Terminated {
            get { return _window == null || _window.IsClosed || _scene == null || _terminated; }
        }

        public static void Initialize() {
            _terminated = false;
            CreateWindowParams wParams = new CreateWindowParams();
            wParams.Title = Resources.Application.GameName.ToString();
            wParams.Size = Constants.DisplaySize;
            wParams.WindowPosition = WindowPosition.CenterScreen;
            _window = new DisplayWindow(wParams);
            Data.Initialize();
        }

        public static void Run() {
            Mouse.Hide();
            while (!Terminated) {
                try {
                    _scene.NextFrame();
                } catch (Exception e) {
                    ErrorReport(e, true);
                    break;
                }
            }
            if (_window != null && !_window.IsClosed)
                _window.SetWindowed();
        }

        public static void NewGame() {
            Game.NewGame(new HotSeatGameMode(), Randomizer.Global.Next());
        }
        public static void NewNetGame() {
            CurrentScene = new DirectConnectScene();
        }
        public static void StartDeckManager() {
            CurrentScene = new DeckManagerScene();
        }

        public static void Terminate() {
            _terminated = true;
        }

        public static void ReturnToMenu() {
            if (CurrentScene is MainMenu)
                Terminate();
            else
                CurrentScene = MainMenu.Instance;
        }

        public static void ToggleFullScreen() {
            if (_window != null) {
                if (_window.IsFullScreen)
                    _window.SetWindowed();
                else
                    _window.SetFullScreen();
            }
        }

        public static void RestoreRenderTarget() {
            Display.RenderTarget = _window;
        }

        public static void ErrorReport(Exception e, bool showMessage) {
            Console.WriteLine("Error: ({0}) {1}", e.GetType().Name, e.Message);
            Console.WriteLine(e.StackTrace);
            using (TextWriter wr = new StreamWriter("error.log", true)) {
                wr.WriteLine("Date: {0}", DateTime.Now);
                wr.WriteLine("Error: ({0}) {1}", e.GetType().Name, e.Message);
                wr.WriteLine(e.StackTrace);
                wr.WriteLine();
            }
            if (showMessage) {
                bool hide = Mouse.IsHidden;
                if (hide)
                    Mouse.Show();
                MessageBox.Show(Resources.Application.ErrorMessage.GetText(), Resources.Application.Error.GetText(), MessageBoxButtons.OK, MessageBoxIcon.Error);
                if (hide)
                    Mouse.Hide();
            }
        }
    }
}
